/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Editoren;

import com.jme3.app.SimpleApplication;
import com.jme3.collision.CollisionResults;
import com.jme3.input.KeyInput;
import com.jme3.input.MouseInput;
import com.jme3.input.controls.AnalogListener;
import com.jme3.input.controls.KeyTrigger;
import com.jme3.input.controls.MouseAxisTrigger;
import com.jme3.input.controls.MouseButtonTrigger;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Ray;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Spatial.CullHint;
import com.jme3.scene.debug.Grid;
import com.jme3.scene.debug.WireFrustum;
import com.jme3.terrain.geomipmap.TerrainPatch;
import com.jme3.terrain.geomipmap.TerrainQuad;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture.WrapMode;
import java.awt.Dimension;

/**
 *
 * @author geez
 */
public class WorldEditApp extends SimpleApplication {

    private Dimension mapsize = new Dimension(9, 9);
    private float[] heightmap;
    private TerrainQuad terrainquad;
    private Material terrainmaterial;
    private int patchSize = 3;
    private int totalSize = 9;

    @Override
    public void simpleInitApp() {
        caminit();
        setupInput();
        mapinit();
        initGrid(Vector3f.ZERO, mapsize.width, mapsize.height, ColorRGBA.White);
    }

    private void caminit() {
        cam.setLocation(new Vector3f(0, 10, 0));
        cam.setRotation(new Quaternion().fromAngleAxis(FastMath.PI / 6, Vector3f.UNIT_X));
        flyCam.setDragToRotate(true);
        flyCam.setMoveSpeed(50);

    }

    private void mapinit() {
        setupMaterial();
        heightmap = new float[mapsize.height * mapsize.width];

        terrainquad = new TerrainQuad("mapquad", patchSize, totalSize, heightmap);
        terrainquad.setMaterial(terrainmaterial);

        rootNode.attachChild(terrainquad);
    }

    private void setupMaterial() {
        terrainmaterial = new Material(assetManager, "Common/MatDefs/Terrain/Terrain.j3md");

        /** 1.1) Add ALPHA map (for red-blue-green coded splat textures) */
        terrainmaterial.setTexture("Alpha", assetManager.loadTexture(
                "Textures/splatmap.png"));

        /** 1.2) Add GRASS texture into the red layer (Tex1). */
        Texture grass = assetManager.loadTexture(
                "Textures/grass.jpg");
        grass.setWrap(WrapMode.Repeat);
        terrainmaterial.setTexture("Tex1", grass);
        terrainmaterial.setFloat("Tex1Scale", 64f);

        /** 1.3) Add DIRT texture into the green layer (Tex2) */
        Texture dirt = assetManager.loadTexture(
                "Textures/dry_earth_with_weeds_4060444.JPG");
        dirt.setWrap(WrapMode.Repeat);
        terrainmaterial.setTexture("Tex2", dirt);
        terrainmaterial.setFloat("Tex2Scale", 32f);

        /** 1.4) Add ROAD texture into the blue layer (Tex3) */
        Texture rock = assetManager.loadTexture(
                "Textures/crazy_stone_9101045.JPG");
        rock.setWrap(WrapMode.Repeat);
        terrainmaterial.setTexture("Tex3", rock);
        terrainmaterial.setFloat("Tex3Scale", 128f);
        terrainmaterial.getAdditionalRenderState().setWireframe(true);
    }

    private Geometry initGrid(Vector3f pos, int width, int height, ColorRGBA color) {
        Geometry g = new Geometry("wireframe grid", new Grid(width, height, 1f));
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat.getAdditionalRenderState().setWireframe(true);
        mat.setColor("Color", color);
        g.setMaterial(mat);
        g.center().move(pos.x, pos.y, pos.z);
        g.setCullHint(CullHint.Never);
        rootNode.attachChild(g);
        return g;
    }

    private void setupInput() {
        inputManager.clearMappings();
        inputManager.addMapping("Forward", new KeyTrigger(KeyInput.KEY_W));
        inputManager.addMapping("Backward", new KeyTrigger(KeyInput.KEY_S));
        inputManager.addMapping("Left", new KeyTrigger(KeyInput.KEY_A));
        inputManager.addMapping("Right", new KeyTrigger(KeyInput.KEY_D));
        inputManager.addMapping("WheelUp", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, false));
        inputManager.addMapping("WheelDown", new MouseAxisTrigger(MouseInput.AXIS_WHEEL, true));
        inputManager.addMapping("Click", new MouseButtonTrigger(MouseInput.BUTTON_LEFT));
        AnalogListener analogListener = new AnalogListener() {

            private int speed = 50;

            public void onAnalog(String name, float value, float tpf) {
                Vector3f loc = cam.getLocation();
                if (name.equals("Forward")) {
                    cam.setLocation(new Vector3f(loc.x, loc.y, loc.z + value * speed));
                } else if (name.equals("Backward")) {
                    cam.setLocation(new Vector3f(loc.x, loc.y, loc.z - value * speed));
                } else if (name.equals("Left")) {
                    cam.setLocation(new Vector3f(loc.x + value * speed, loc.y, loc.z));
                } else if (name.equals("Right")) {
                    cam.setLocation(new Vector3f(loc.x - value * speed, loc.y, loc.z));
                } else if (name.equals("WheelUp")) {
                    cam.setLocation(new Vector3f(loc.x, loc.y - value, loc.z + value));
                } else if (name.equals("WheelDown")) {
                    cam.setLocation(new Vector3f(loc.x, loc.y + value, loc.z - value));
                } else if (name.equals("Click")) {
                    if (pausetime <= 0) {
                        clicked();
                        pausetime = 1;
                    }

                }

            }
        };
        inputManager.addListener(analogListener, new String[]{"Forward", "Backward", "Left", "Right", "WheelUp", "WheelDown", "Click"});
    }
    private float pausetime = 0;

    @Override
    public void simpleUpdate(float tpf) {
        if (pausetime > 0) {
            pausetime -= tpf;
            System.out.println("Pause: " + pausetime + " tpf: " + tpf);
        }
        if(true){
            
        }
    }

    private void clicked() {
        if (true) {
            CollisionResults results = new CollisionResults();
            Vector2f click2d = inputManager.getCursorPosition();
            Vector3f click3d = cam.getWorldCoordinates(
                    new Vector2f(click2d.x, click2d.y), 0f).clone();
            Vector3f dir = cam.getWorldCoordinates(
                    new Vector2f(click2d.x, click2d.y), 1f).subtractLocal(click3d).normalizeLocal();
            Ray ray = new Ray(click3d, dir);
            terrainquad.collideWith(ray, results);
            if (results.size() >= 1) {
                TerrainPatch g = (TerrainPatch) results.getFarthestCollision().getGeometry();
                terrainquad.setHeight(new Vector2f(g.getOffset().x, g.getOffset().y), terrainquad.getHeight(g.getOffset()) + 1);

            }

        }
    }

    private class myrender extends RenderState {

        public myrender() {
        }
    }
}